package com.spcmg.service.impl;

import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.spcmg.entity.SpcRoom;
import com.spcmg.entity.SpcStation;
import com.spcmg.enums.EnumSysCode;
import com.spcmg.service.ISpcMgUploadService;
import com.spcmg.service.ISpcRoomService;
import com.spcmg.service.ISpcStationService;
import com.spcmg.utils.DateUtil;
import com.spcmg.utils.SequenceIdGenerator;
import com.spcmg.vo.SpcImportFaultVO;
import com.spcmg.vo.UploadSpcRoomVO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SpcMgUploadServiceImpl implements ISpcMgUploadService {

    @Resource
    private ISpcRoomService spcRoomService;

    @Resource
    private SequenceIdGenerator sequenceIdGenerator;

    @Resource
    private ISpcStationService spcStationService;

    @Override
    public void upload(MultipartFile file, Integer handlePerTimes, HttpServletResponse res) throws Exception {
        Long importId = sequenceIdGenerator.nextId();
        Map<String, SpcRoom> passedMap = new HashMap<>();
        Map<String, SpcStation> newStationMap = new HashMap<>();
        List<SpcImportFaultVO> rejectList = new ArrayList<>();
        // 读取数据
        BufferedReader br = new BufferedReader(new InputStreamReader(file.getInputStream(), "GBK"));
        String line = "";
        int i = 0;
        br.readLine();
        while ((line = br.readLine()) != null) {
            // 校验数据是否合法
            String[] data = line.split(",");
            if (data.length == 10) {
                UploadSpcRoomVO vo = this.buildVO(data, line);
                if (this.checkData(vo, passedMap)) {
                    // 查询局站Id，查询是否在新建局站里
                    if (newStationMap.containsKey(vo.getStationName())) {
                        SpcStation newStation = newStationMap.get(vo.getStationName());
                        vo.setStationId(newStation.getStationId());
                    } else {
                        // 查询局站Id，查询数据库
                        Long stationId = spcStationService.selectIdByChinaName(vo.getStationName());
                        if (stationId != null && stationId > 0L) {
                            // 设置局站Id并加入通过列表
                            vo.setStationId(stationId);
                        } else {
                            // 设置新局站信息并加入新局站列表
                            SpcStation spcStation = new SpcStation();
                            spcStation.setStationId(sequenceIdGenerator.nextId());
                            spcStation.setChinaName(vo.getStationName());
                            newStationMap.put(vo.getStationName(), spcStation);
                            // 设置局站Id并加入通过列表
                            vo.setStationId(spcStation.getStationId());
                        }
                    }
                    passedMap.put(vo.getChinaName(), this.buildEntity(vo));
                } else {
                    // 数据有问题加入失败列表
                    SpcImportFaultVO spcImportFault = new SpcImportFaultVO();
                    spcImportFault.setImportId(importId);
                    spcImportFault.setFaultData(vo.getStrData());
                    spcImportFault.setFaultReason(vo.getFaultReason());
                    rejectList.add(spcImportFault);
                }
                if (passedMap.size() % handlePerTimes == 0) {
                    // 保存数据库一次
                    if (!passedMap.isEmpty()) {
                        spcRoomService.saveBatchData(passedMap.values(), newStationMap.values());
                        // 保存后初始化
                        passedMap.clear();
                        newStationMap.clear();
                    }
                }
            }
        }
        // 保存剩余的数据（之前是按照handlePerTimes保存的，如果不是整数倍则会有剩余数据）。
        if (!passedMap.isEmpty()) {
            spcRoomService.saveBatchData(passedMap.values(), newStationMap.values());
            // 保存后初始化
            passedMap.clear();
            newStationMap.clear();
        }
        // 查询错误信息
        StringBuilder sb = new StringBuilder("机房ID,机房名称,所属局站名称,机房地址,经度,纬度,,机房等级,机房类型,投产时间,数据错误原因\n");
        for (SpcImportFaultVO fault : rejectList) {
            sb.append(fault.getFaultData());
            sb.append(",");
            sb.append(fault.getFaultReason());
            sb.append("\n");
        }
        byte[] bs = sb.toString().getBytes(StandardCharsets.UTF_8);

        res.reset();
        res.setContentType("application/force-download");
        res.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(importId + ".csv", "UTF-8"));
        OutputStream out = res.getOutputStream();
        out.write(bs, 0, bs.length);
        out.flush();
    }

    /**
     * 根据csv行数据创建VO
     *
     * @param data
     * @param src
     * @return
     */
    private UploadSpcRoomVO buildVO(String[] data, String src) {
        UploadSpcRoomVO vo = new UploadSpcRoomVO();
        vo.setStrData(src);
        vo.setRoomId(Strings.isNullOrEmpty(data[0]) ? null : Long.valueOf(data[0]));
        vo.setChinaName(data[1]);
        vo.setStationName(data[2]);
        vo.setAddress(data[3]);
        vo.setX(Strings.isNullOrEmpty(data[4]) ? null : new BigDecimal(data[4]).setScale(6, RoundingMode.HALF_DOWN));
        vo.setY(Strings.isNullOrEmpty(data[5]) ? null : new BigDecimal(data[5]).setScale(6, RoundingMode.HALF_DOWN));
        vo.setClassId(Strings.isNullOrEmpty(data[7]) ? null : Integer.valueOf(data[7]));
        vo.setTypeId(Strings.isNullOrEmpty(data[8]) ? null : Integer.valueOf(data[8]));
        try {
            vo.setStartUseDate(Strings.isNullOrEmpty(data[9]) ? null : DateUtil.parseLdt(data[9], "yyyy-MM-dd HH:mm:ss"));
        } catch (Exception ex) {
            // 格式化出错，不用处理
        }
        return vo;
    }

    /**
     * 根据CSV的VO数据创建实体
     *
     * @param vo
     * @return
     */
    private SpcRoom buildEntity(UploadSpcRoomVO vo) {
        SpcRoom entity = new SpcRoom();
        entity.setRoomId(vo.getRoomId());
        entity.setChinaName(vo.getChinaName());
        entity.setStationId(vo.getStationId());
        entity.setAddress(vo.getAddress());
        entity.setX(vo.getX());
        entity.setY(vo.getY());
        entity.setStartUseDate(vo.getStartUseDate());
        entity.setClassId(vo.getClassId());
        entity.setTypeId(vo.getTypeId());
        return entity;
    }

    /**
     * 校验VO
     *
     * @param vo
     * @param passedMap
     * @return
     */
    private Boolean checkData(UploadSpcRoomVO vo, Map<String, SpcRoom> passedMap) {
        List<String> faultList = new ArrayList<>();
        // 机房等级
        if (vo.getClassId() == null || vo.getClassId() <= 0) {
            faultList.add(EnumSysCode.ERR_5003.getMsg());
        }
        // 机房类型
        if (vo.getTypeId() == null || vo.getTypeId() <= 0) {
            faultList.add(EnumSysCode.ERR_5004.getMsg());
        }
        // 机房类型为IDC, 可出租机架数，已出租机架数
        if (vo.getTypeId() != null && vo.getTypeId() == 2050053) {
            faultList.add(EnumSysCode.ERR_5005.getMsg());
            faultList.add(EnumSysCode.ERR_5006.getMsg());
        }
        // 经纬度坐标
        if (vo.getX() == null || vo.getY() == null) {
            faultList.add(EnumSysCode.ERR_5001.getMsg());
        }
        // 开始使用日期
        if (vo.getStartUseDate() == null) {
            faultList.add(EnumSysCode.ERR_5007.getMsg());
        }
        // 机房名称
        if (passedMap.containsKey(vo.getChinaName())) {
            // 先查询此次插入的列表中是否重复
            faultList.add(EnumSysCode.ERR_5002.getMsg());
        }
//        else {
//            // 再查询数据库中机房名称是否重复
//            Integer count = spcRoomService.selectCountByRoomChinaName(vo.getChinaName());
//            if (count > 0) {
//                faultList.add(EnumSysCode.ERR_5002.getMsg());
//            }
//        }
        // 如果错误列表里有值，说明校验失败
        if (faultList.isEmpty()) {
            vo.setChecked(true);
        } else {
            vo.setChecked(false);
            vo.setFaultReason(Joiner.on(",").join(faultList));
        }
        return vo.getChecked();
    }

    public static void main(String[] args) {
        String s = null;
        Long l = Long.parseLong(s);
        new BigDecimal(s);
        System.out.println(l);
    }
}
